package org.hehui.supervisorysystem.ui.Preference.DatabasePPage;

import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Spinner;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.hehui.supervisorysystem.Activator;
import org.hehui.supervisorysystem.util.IAppConstants;


public class DataBasePreferencePage extends PreferencePage implements
		IWorkbenchPreferencePage, ModifyListener {

	private Text DBNameText;
	private Combo DBTypeCombo;
	private Text classNameText;
	private Text passwordText;
	private Text userNameText;
	private Text hostText;
	private Spinner portSpinner;
	private Spinner pagingSpinner;
	private Text URLText;
	private Button enablePagingButton;
	//private Combo classNameCombo;
	
	private IPreferenceStore ps;

	///////////
	private static final String mySQLName = "MySQL";
	private static final String mySQLClassName = "com.mysql.jdbc.Driver";
	private static final int mySQLDefaultPort = 3306;
	private static final String mySQLURL = "jdbc:mysql//<Server>:<Port>/<DataBase>";
	
	private static final String derbyName = "Apache Derby";
	private static final String derbyClassName = "org.apache.derby.jdbc.ClientDriver";
	private static final int derbyDefaultPort = 1527;
	private static final String derbyURL = " jdbc:derby://<Server>:<Port>/<DataBase>";
	
	private static final String oracleName = "Oracle";
	private static final String oracleClassName = "oracle.jdbc.driver.OracleDriver";
	private static final int oracleDefaultPort = 1521;
	private static final String oracleURL = "jdbc:oracle:thin:@<Server>:<Port>:<DataBase>";
	
	private static final String msSQLServerName = "M$ SQL Server";
	private static final String msSQLServerClassName = "net.sourceforge.jtds.jdbc.Driver";
	private static final int msSQLServerDefaultPort = 1433;
	private static final String msSQLServerURL = "jdbc:jtds:sqlserver://<Server>:<Port>;DatabaseName=<DataBase>";
	
	String[] DBTypes = new String[]{mySQLName, derbyName, oracleName, msSQLServerName};
	String[] DBClassNames = new String[]{mySQLClassName, derbyName, oracleName, msSQLServerName};
	String[] URLs = new String[]{mySQLURL, derbyURL, oracleURL, msSQLServerURL};
	///////////////////
	
	private static final String DBNAME_KEY = IAppConstants.DBNAME_KEY;	
	private static final String DBNAME_DEF = "memory";
	
	private static final String DBTYPE_KEY = IAppConstants.DBTYPE_KEY;
	private static final int DBTYPE_DEF = 0;	
	
	private static final String CLASSNAME_KEY = IAppConstants.CLASSNAME_KEY;
	private static final String CLASSNAME_DEF = "com.mysql.jdbc.Driver";
	
	private static final String URL_KEY = IAppConstants.URL_KEY;
	private static final String URL_DEF = "jdbc:mysql//localhost:3306/memory";
	
	private static final String HOST_KEY = IAppConstants.HOST_KEY;
	private static final String HOST_DEF = "localhost";
	
	private static final String PORT_KEY = IAppConstants.PORT_KEY;
	private static final int PORT_DEF = 3306;
	
	private static final String USERNAME_KEY = "$USERNAME_KEY";
	private static final String USERNAME_DEF = "hehui";
	
	private static final String PASSWORD_KEY = IAppConstants.PASSWORD_KEY;
	private static final String PASSWORD_DEF = "hehui";
		
	private static final String ENABLEPAGING_KEY = IAppConstants.ENABLEPAGEBREAKING_KEY;
	private static final Boolean ENABLEPAGEBREAKING_DEF = true;
	
	private static final String PAGINGSIZE_KEY = IAppConstants.PAGEBREAKINGSIZE_KEY;
	private static final int PAGEBREAKING_DEF = IAppConstants.PAGEBREAKING_DEF;
	

	public DataBasePreferencePage() {
		// TODO Auto-generated constructor stub
	}

	public DataBasePreferencePage(String title) {
		super(title);
		// TODO Auto-generated constructor stub
	}

	public DataBasePreferencePage(String title, ImageDescriptor image) {
		super(title, image);
		// TODO Auto-generated constructor stub
	}

	@Override
	public Control createContents(Composite parent) {
		
		Composite container = new Composite(parent, SWT.NULL);
		final GridLayout gridLayout = new GridLayout();
		gridLayout.numColumns = 4;
		container.setLayout(gridLayout);

		final Label DBTypeLabel = new Label(container, SWT.NONE);
		DBTypeLabel.setText("DB Type:");

		DBTypeCombo = new Combo(container, SWT.READ_ONLY);
		DBTypeCombo.setItems(DBTypes);
		DBTypeCombo.select(0);
		final GridData gd_dBTypeCombo = new GridData(SWT.FILL, SWT.CENTER, true, false);
		DBTypeCombo.setLayoutData(gd_dBTypeCombo);
		DBTypeCombo.addSelectionListener(new SelectionAdapter(){
			public void widgetSelected(SelectionEvent e){
				//MessageDialog.openInformation(null, "Selected", DBTypeCombo.getText());
				switch (DBTypeCombo.getSelectionIndex()) {
				case 0:
					modifyTextState(mySQLClassName, mySQLURL, 3306, false);
					break;
				case 1:
					modifyTextState(derbyClassName, derbyURL, 1527, false);
					break;
				case 2:
					modifyTextState(oracleClassName, oracleURL, 1521, false);
					break;
				case 3:
					modifyTextState(msSQLServerClassName, msSQLServerURL, 1433, false);
					break;
				case 4:
					modifyTextState("", "", 0, true);
					break;


				default:
					break;
				}
			}
		});

		final Label DBNameLabel = new Label(container, SWT.NONE);
		final GridData gd_dBNameLabel = new GridData();
		DBNameLabel.setLayoutData(gd_dBNameLabel);
		DBNameLabel.setText("DB Name:");

		//DBNameText = new Text(container, SWT.BORDER | SWT.PASSWORD);
		DBNameText = createText(container, true, DBNAME_KEY, DBNAME_DEF);
		final GridData gd_dBNameText = new GridData(SWT.FILL, SWT.CENTER, true, false);
		DBNameText.setLayoutData(gd_dBNameText);
		

		final Label classNameLabel = new Label(container, SWT.NONE);
		classNameLabel.setLayoutData(new GridData());
		classNameLabel.setText("ClassName:");

//		classNameCombo = new Combo(container, SWT.READ_ONLY);	
//		classNameCombo.setItems(new String[] {"com.mysql.jdbc.Driver", "org.apache.derby.jdbc.ClientDriver", "org.apache.derby.jdbc.EmbeddedDriver", "oracle.jdbc.driver.OracleDriver", "net.sourceforge.jtds.jdbc.Driver"});
//		classNameCombo.select(0);		
//		final GridData gd_classNameCombo = new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1);
//		classNameCombo.setLayoutData(gd_classNameCombo);
		
		classNameText = createText(container, false, CLASSNAME_KEY, CLASSNAME_DEF);
		final GridData gd_classNameText = new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1);
		classNameText.setLayoutData(gd_classNameText);
		classNameText.setEnabled(false);
		
		

		final Label hostLabel = new Label(container, SWT.NONE);
		hostLabel.setLayoutData(new GridData());
		hostLabel.setText("Host:");
		//hostText = new Text(container, SWT.BORDER | SWT.PASSWORD);
		hostText = createText(container, true, HOST_KEY, HOST_DEF);
		final GridData gd_hostText = new GridData(SWT.FILL, SWT.CENTER, true, false);
		hostText.setLayoutData(gd_hostText);

		final Label portLabel = new Label(container, SWT.NONE);
		portLabel.setLayoutData(new GridData());
		portLabel.setText("Port:");
		portSpinner = createSpinner(container, PORT_KEY, 3306, 1, 65535, 1);;
		portSpinner.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
		//portSpinner.setPageIncrement(1);
		//portSpinner.setMaximum(65535);
		//portSpinner.setSelection(3306);

		final Label urlLabel = new Label(container, SWT.NONE);
		urlLabel.setLayoutData(new GridData());
		urlLabel.setText("URL:");
		//URLText = new Text(container, SWT.BORDER);
		URLText = createText(container, false, URL_KEY, URL_DEF);
		final GridData gd_uRLText = new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1);
		URLText.setLayoutData(gd_uRLText);
		URLText.setEnabled(false);

		final Label userNameLabel = new Label(container, SWT.NONE);
		userNameLabel.setText("User Name:");
		//userNameText = new Text(container, SWT.BORDER | SWT.PASSWORD);
		userNameText = createText(container, true, USERNAME_KEY, USERNAME_DEF);
		final GridData gd_userNameText = new GridData(SWT.FILL, SWT.CENTER, true, false);
		userNameText.setLayoutData(gd_userNameText);

		final Label passwordLabel = new Label(container, SWT.NONE);
		passwordLabel.setLayoutData(new GridData());
		passwordLabel.setText("Password:");
		//passwordText = new Text(container, SWT.BORDER | SWT.PASSWORD);
		passwordText = createText(container, true, PASSWORD_KEY, PASSWORD_DEF);
		final GridData gd_passwordText = new GridData(SWT.FILL, SWT.CENTER, true, false);
		passwordText.setLayoutData(gd_passwordText);
		//passwordText.setEchoChar('*');

		/*	
		final Label pageBreakingLabel = new Label(container, SWT.NONE);
		pageBreakingLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 3, 1));
		pageBreakingLabel.setText("Page Breaking(Rows pre Page):");
		
		pageBreakingSpinner = createSpinner(container, PAGEBREAKING_KEY, 100, 1, 1000, 10);
		//pageBreakingSpinner.setMinimum(1);
		//pageBreakingSpinner.setMaximum(1000);
		//pageBreakingSpinner.setIncrement(10);
		final GridData gd_pageBreakingSpinner = new GridData(SWT.RIGHT, SWT.CENTER, false, false);
		pageBreakingSpinner.setLayoutData(gd_pageBreakingSpinner);
		//pageBreakingSpinner.setSelection(isEmpty(ps.getString("$PAGEBREAKING_KEY"))?100:100);		
		*/
		
		final Group pagingGroup = new Group(container, SWT.NONE);
		pagingGroup.setText("Paging");
		final GridData gd_pageBreakingGroup = new GridData(SWT.FILL, SWT.FILL, true, false, 4, 1);
		pagingGroup.setLayoutData(gd_pageBreakingGroup);
		final GridLayout gridLayout_1 = new GridLayout();
		gridLayout_1.numColumns = 3;
		pagingGroup.setLayout(gridLayout_1);

		enablePagingButton = new Button(pagingGroup, SWT.CHECK);
		Boolean isPBEnabled = ps.getBoolean(ENABLEPAGING_KEY);
		enablePagingButton.setSelection(isPBEnabled);
		enablePagingButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				pagingSpinner.setEnabled(enablePagingButton.getSelection());				
			}
		});
		final GridData gd_enablePagebreakingButton = new GridData(SWT.FILL, SWT.CENTER, true, false);
		enablePagingButton.setLayoutData(gd_enablePagebreakingButton);
		enablePagingButton.setText("Enable Paging");
		//passwordText.setEchoChar('*');
		
		final Label limitRowsLabel = new Label(pagingGroup, SWT.NONE);
		limitRowsLabel.setText("Limit Rows:");
		
		pagingSpinner = createSpinner(pagingGroup, PAGINGSIZE_KEY, 100, 1, 1000, 10);
		pagingSpinner.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));		
		pagingSpinner.setEnabled(isPBEnabled);
		
		
		return container;
	}
	
	private Text createText(Composite composite, boolean isPassword, String storeKey, String defaultValue){
		
		Text text;
		if(isPassword){
			text = new Text(composite, SWT.BORDER | SWT.PASSWORD);
		}else{
			text = new Text(composite, SWT.BORDER);
		}
		
		String value = ps.getString(storeKey);
		text.setText(isEmpty(value)?defaultValue:value);
		text.addModifyListener(this);
		
		return text;
	}
	
	private Spinner createSpinner(Composite composite, String storeKey, int defaultValue, int minimum, int maximum, int increment){
		Spinner spinner = new Spinner(composite, SWT.BORDER);
		spinner.setMinimum(minimum);
		spinner.setMaximum(maximum);
		spinner.setIncrement(increment);
		
		int value = ps.getInt(storeKey);
		String valueString = ps.getString(storeKey);
		spinner.setSelection(isEmpty(valueString)?defaultValue:value);
				
		return spinner;		
	}
	
	private void modifyTextState(String className, String URLString, int port, boolean isEnabled){
		classNameText.setText(className);
		classNameText.setEnabled(isEnabled);
		
		URLText.setText(URLString);
		URLText.setEnabled(isEnabled);
		
		portSpinner.setSelection(port);
		
	}
	
	boolean isEmpty(String string){
		return string == null || string.trim().isEmpty();
	}

	@Override
	public void init(IWorkbench workbench) {
		setPreferenceStore(Activator.getDefault().getPreferenceStore());
		ps = getPreferenceStore();
	}
	
	@Override
	public void modifyText(ModifyEvent e) {
		String errString = null;
		if(isEmpty(DBNameText.getText())){
			errString = "DataBase Name Can Not Be Empty!";
		}else if(isEmpty(classNameText.getText())){
			errString = "ClassName Can Not Be Empty!";
		}else if(isEmpty(URLText.getText())){
			errString = "URL Can Not Be Empty!";
		}else if(isEmpty(hostText.getText())){
			errString = "Host Can Not Be Empty!";
		}else if(isEmpty(userNameText.getText())){
			errString = "User Name Can Not Be Empty!";
		}else if(isEmpty(passwordText.getText())){
			errString = "Password Can Not Be Empty!";
		}
		
		setErrorMessage(errString);
		setValid(errString == null);
		getApplyButton().setEnabled(errString == null);
		
	}

	@Override
	protected void performDefaults() {
		URLText.setText(URL_DEF);
		hostText.setText(HOST_DEF);
		portSpinner.setSelection(PORT_DEF);
		userNameText.setText(USERNAME_DEF);
		passwordText.setText(PASSWORD_DEF);
		pagingSpinner.setSelection(PAGEBREAKING_DEF);
		
	}
	
	@Override
	protected void performApply() {
		doSave();
	}

	private void doSave() {
		ps.setValue(DBTYPE_KEY, DBTypeCombo.getSelectionIndex());
		ps.setValue(DBNAME_KEY, DBNameText.getText().trim());
		ps.setValue(CLASSNAME_KEY, classNameText.getText().trim());	
		ps.setValue(HOST_KEY, hostText.getText().trim());
		ps.setValue(PORT_KEY, portSpinner.getSelection());
		ps.setValue(URL_KEY, URLText.getText().trim());
		ps.setValue(USERNAME_KEY, userNameText.getText().trim());
		ps.setValue(PASSWORD_KEY, passwordText.getText().trim());
		ps.setValue(ENABLEPAGING_KEY, enablePagingButton.getSelection()?true:false);
		ps.setValue(PAGINGSIZE_KEY, pagingSpinner.getSelection());
		
		
	}

	@Override
	public boolean performOk() {
		doSave();
		return true;
	}
	
	

}
